﻿using System;
using System.Collections.Generic;
using Antlr.Runtime;
using Magic.Framework.OQL.Expressions;
using Magic.Framework.OQL.Factory;
using Magic.Framework.OQL.Expressions.Predicate;

namespace Magic.Framework.OQL
{
    public class SqlUtil
    {
        private static IDictionary<string, int> _typeMapping = new Dictionary<string, int>();
        static SqlUtil()
        {
            _typeMapping.Add("=", SQLParser.Eq);
            _typeMapping.Add("<>", SQLParser.Neq1);
            _typeMapping.Add("!=", SQLParser.Neq2);
            _typeMapping.Add("<=", SQLParser.Le1);
            _typeMapping.Add("!>", SQLParser.Le2);
            _typeMapping.Add("<", SQLParser.Lt);
            _typeMapping.Add(">=", SQLParser.Ge1);
            _typeMapping.Add("!<", SQLParser.Ge2);
            _typeMapping.Add(">", SQLParser.Gt);
            
        }

        private SqlUtil()
        {
        }

        public static QueryStatement CompileQuery(string oql)
        {
            if (string.IsNullOrEmpty(oql)) return null;
            SQLParser.start_return statements = null;

            try
            {
                SQLLexer lex = new SQLLexer(new CaseInsensitiveStringStream(oql));
                CommonTokenStream tokens = new CommonTokenStream(lex);
                SQLParser parser = new SQLParser(tokens);
                parser.TreeAdaptor = new TreeFactory();
                //statements = parser.start();
            }
            catch (Exception e)
            {
                throw e;
            }

            QueryStatement query = null;
            if (statements != null && statements.Tree != null)
            {
                if (!statements.Tree.IsNil) query = statements.Tree as QueryStatement;
                if (query == null && statements.Tree._children != null && statements.Tree._children.Count > 0)
                    query = statements.Tree._children[0] as QueryStatement;
            }
            return query;
        }

        //predicates
        
       /*
        public static Expression CreateComparison(string columnName, string paramName, string operatorString)
        {
            Comparison exp = new Comparison(new CommonToken(Comparison.TreeType));
            Identifier identifier = new Identifier(new CommonToken(Identifier.TreeType, columnName));
            exp.AddChild(identifier);

            Text text = new Text(new CommonToken(_typeMapping[operatorString], operatorString));
            exp.AddChild(text);

            UserVariable variable = new UserVariable(new CommonToken(UserVariable.TreeType, paramName));
            exp.AddChild(variable);

            return exp;
        }*/
       

        //conditions
        public static Expression CreateAnd(Expression left, Expression right)
        {
            if (left == null) return right; //right can also be null.
            if (right == null) return left;
            And exp = new And(new CommonToken(And.TreeType, "AND"));
            exp.AddChild(left);
            exp.AddChild(right);
            return exp;
        }
        public static Expression CreateOr(Expression left, Expression right)
        {
            if (left == null) return right; //right can also be null.
            if (right == null) return left;
            Or exp = new Or(new CommonToken(Or.TreeType, "OR"));
            exp.AddChild(left);
            exp.AddChild(right);
            return exp;
        }
        public static Expression CreateNot(Expression exp)
        {
            if (exp == null) return null;
            Not expNot = new Not(new CommonToken(Not.TreeType, "NOT"));
            expNot.AddChild(exp);
            return expNot;
        }
       

        public static WhereClause CreateWhere()
        {
            IToken whereClauseToken = new CommonToken(WhereClause.TreeType);
            WhereClause clause = new WhereClause(whereClauseToken);
            clause.AddChild(new Text(new CommonToken(SQLParser.WHERE, "WHERE")));
            return clause;
        }
        
    }
}